package me.helllp.dake.common.security;

import lombok.extern.slf4j.Slf4j;
import me.helllp.dake.common.exception.DakeDecryptException;
import me.helllp.dake.common.exception.DakeEncryptException;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

@Slf4j
public class AesCrypto {
    private static final String ALG_NAME = "AES";

    private static final String CHARSET_NAME = "UTF-8";

    public static byte[] encrypt(AESEnum aesEnum, byte[] data, byte[] key, byte[] iv) throws DakeEncryptException {
        try {
            Cipher cipher = Cipher.getInstance(aesEnum.getAlgName());
            SecretKeySpec keySpec = new SecretKeySpec(key, ALG_NAME);
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec);
            return cipher.doFinal(data);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException |
                 InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            log.info("encrypt exception:", e);
            throw new DakeEncryptException();
        }
    }

    public static String encrypt(AESEnum aesEnum, String text,String key,String iv) throws DakeEncryptException {
        byte[] encData = encrypt(aesEnum, CryptoUtil.decode(text), CryptoUtil.decode(key), CryptoUtil.decode(iv));
        return Base64.encodeBase64String(encData);
    }

    public static byte[] decrypt(AESEnum aesEnum, byte[] data, byte[] key, byte[] iv) throws DakeDecryptException {
        try{
            Cipher cipher = Cipher.getInstance(aesEnum.getAlgName());
            SecretKeySpec keySpec = new SecretKeySpec(key, ALG_NAME);
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);
            return cipher.doFinal(data);
        } catch (InvalidAlgorithmParameterException | NoSuchPaddingException |
                 IllegalBlockSizeException | NoSuchAlgorithmException | BadPaddingException | InvalidKeyException  e) {
            log.info("decrypt exception:", e);
            throw new DakeDecryptException();
        }

    }
    /**
     * 解密
     * @param pass   密文
     * @param key    密钥
     * @param iv     向量
     * @return
     */
    public static String decrypt(AESEnum aesEnum, String pass,String key,String iv) throws DakeDecryptException {
        byte[] decData = decrypt(aesEnum, Base64.decodeBase64(pass), Base64.decodeBase64(key), Base64.decodeBase64(iv));
        return Base64.encodeBase64String(decData);
    }
}
